x86: allow reading MSR_IA32_TSC with XENPF_resource_op
authorChao Peng <chao.p.peng@linux.intel.com>
Wed, 28 Jan 2015 15:33:01 +0000 (16:33 +0100)
committerJan Beulich <jbeulich@suse.com>
Wed, 28 Jan 2015 15:36:36 +0000 (16:36 +0100)
Memory bandwidth monitoring requires system time information returned
along with the monitoring counter to verify the correctness of the
counter value and to calculate the time elapsed between two samplings.

Add MSR_IA32_TSC to the read path and it returns scaled system time(ns)
instead of raw timestamp to elimanate the needs to convert. The return
time is obfuscated with booting random to eliminate the potential abuse
of it. RESOURCE_ACCESS_MAX_ENTRIES is also increased to 3 so MSR_IA32_TSC
can be used together with an MSR write/read operation pair.

Signed-off-by: Chao Peng <chao.p.peng@linux.intel.com>
Fix uninitialized variable build error.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/platform_hypercall.c
xen/common/random.c
xen/include/public/platform.h
xen/include/xen/random.h

index 32f39b221399fd539df1e1f6bbc4e9b3817929b0..a8dd43432940becdc6d4f7c09ef432ecb671487d 100644 (file)
@@ -61,7 +61,7 @@ long cpu_down_helper(void *data);
 long core_parking_helper(void *data);
 uint32_t get_cur_idle_nums(void);
 
-#define RESOURCE_ACCESS_MAX_ENTRIES 2
+#define RESOURCE_ACCESS_MAX_ENTRIES 3
 struct xen_resource_access {
     unsigned int nr_done;
     unsigned int nr_entries;
@@ -75,6 +75,7 @@ static bool_t allow_access_msr(unsigned int msr)
     /* MSR for CMT, refer to chapter 17.14 of Intel SDM. */
     case MSR_IA32_CMT_EVTSEL:
     case MSR_IA32_CMT_CTR:
+    case MSR_IA32_TSC:
         return 1;
     }
 
@@ -124,6 +125,7 @@ static void resource_access(void *info)
 {
     struct xen_resource_access *ra = info;
     unsigned int i;
+    u64 tsc = 0;
 
     for ( i = 0; i < ra->nr_done; i++ )
     {
@@ -133,10 +135,40 @@ static void resource_access(void *info)
         switch ( entry->u.cmd )
         {
         case XEN_RESOURCE_OP_MSR_READ:
-            ret = rdmsr_safe(entry->idx, entry->val);
+            if ( unlikely(entry->idx == MSR_IA32_TSC) )
+            {
+                /* Return obfuscated scaled time instead of raw timestamp */
+                entry->val = get_s_time_fixed(tsc)
+                             + SECONDS(boot_random) - boot_random;
+                ret = 0;
+            }
+            else
+            {
+                unsigned long flags = 0;
+                /*
+                 * If next entry is MSR_IA32_TSC read, then the actual rdtscll
+                 * is performed together with current entry, with IRQ disabled.
+                 */
+                bool_t read_tsc = (i < ra->nr_done - 1 &&
+                                   unlikely(entry[1].idx == MSR_IA32_TSC));
+
+                if ( unlikely(read_tsc) )
+                    local_irq_save(flags);
+
+                ret = rdmsr_safe(entry->idx, entry->val);
+
+                if ( unlikely(read_tsc) )
+                {
+                    rdtscll(tsc);
+                    local_irq_restore(flags);
+                }
+            }
             break;
         case XEN_RESOURCE_OP_MSR_WRITE:
-            ret = wrmsr_safe(entry->idx, entry->val);
+            if ( unlikely(entry->idx == MSR_IA32_TSC) )
+                ret = -EPERM;
+            else
+                ret = wrmsr_safe(entry->idx, entry->val);
             break;
         default:
             BUG();
index 4a28a24b4c7cfaeda0c8cffdc5a040d0cad79356..cb9187ce9272646b78cd45645a449bd231a9858e 100644 (file)
@@ -1,9 +1,11 @@
+#include <xen/init.h>
 #include <xen/percpu.h>
 #include <xen/random.h>
 #include <xen/time.h>
 #include <asm/random.h>
 
 static DEFINE_PER_CPU(unsigned int, seed);
+unsigned int __read_mostly boot_random;
 
 unsigned int get_random(void)
 {
@@ -27,3 +29,10 @@ unsigned int get_random(void)
 
     return val;
 }
+
+static int __init init_boot_random(void)
+{
+    boot_random = get_random();
+    return 0;
+}
+__initcall(init_boot_random);
index 5c57615819cb300b767479466d2f7f851a4ba1b5..3e340b4148ab3248c0a4a8a174c996e8a11dc9b1 100644 (file)
@@ -540,6 +540,16 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_core_parking_t);
 #define XEN_RESOURCE_OP_MSR_READ  0
 #define XEN_RESOURCE_OP_MSR_WRITE 1
 
+/*
+ * Specially handled MSRs:
+ * - MSR_IA32_TSC
+ * READ: Returns the scaled system time(ns) instead of raw timestamp. In
+ *       multiple entry case, if other MSR read is followed by a MSR_IA32_TSC
+ *       read, then both reads are guaranteed to be performed atomically (with
+ *       IRQ disabled). The return time indicates the point of reading that MSR.
+ * WRITE: Not supported.
+ */
+
 struct xenpf_resource_entry {
     union {
         uint32_t cmd;   /* IN: XEN_RESOURCE_OP_* */
index 7c43d87f59ad728721bead8bdddd79ab656c8240..b950f03c0c3055a9db6c4f9b74a1c9166b14b8c6 100644 (file)
@@ -3,4 +3,7 @@
 
 unsigned int get_random(void);
 
+/* The value keeps unchange once initialized for each booting */
+extern unsigned int boot_random;
+
 #endif /* __XEN_RANDOM_H__ */